package org.cloud.im.admin.common;

import com.fasterxml.jackson.annotation.JsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @Author: w.weidong.lin@abite.com
 * @Description: TODO
 * @Date: create in 2021/10/26 11:18
 */
public class Result<T> implements Serializable, IResult<T> {

    private static final Logger logger = LoggerFactory.getLogger(Result.class);

    private static final Long serialVersionUID = -6029022489278479070L;


    /**
     * 服务状态码，为integer类型， 0 为成功，-1为业务校验错误（手机号格式不对，会员不存在等），-2为服务不可用异常（sql语句异常,空指针等）。-3为请求参数非法<br/>
     */
    private Integer status = SUCCESS_STATUS;
    /**
     * 描述信息。用于返回业务校验错误信息和服务不可用异常信息，不可用于设置日志堆栈信息。举例：业务信息： msg = "手机号格式不对" ，服务不可用异常信息：msg="数据库连接池中没有空闲连接".
     */
    private String msg;

    /**
     * 业务语义状态码，用于业务语义路由，通常和msg搭配使用。当status为-1时，用该code指明具体业务校验错误
     */
    private String code;

    /**
     * 业务正常返回的消息体,每个服务使用专用data对象，不可复用。属性命名规则同数据库命名。支持数据结构包装，例如：List<data>，Set<data>。
     */
    private T data;

    /**
     * 异常堆栈信息
     */
    private String trace;

    public Result() {
    }

    public Result(Integer status, String msg, String code, T data, String trace) {
        this.status = status;
        this.msg = msg;
        this.code = code;
        this.data = data;
        this.trace = trace;
    }

    public Result(Integer status, String msg, String code, T data) {
        this(status, msg, code, data, null);
    }

    public Result(Integer status, String msg, String code) {
        this(status, msg, code, null, null);
    }

    /**
     * 请求是否成功，判断status值是否为{@link #SUCCESS_STATUS}
     *
     * @return
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESS_STATUS.equals(getStatus());
    }

    /**
     * 得到服务异常 Result.msg字段值为"服务器繁忙，请稍候重试！"
     */
    public static <T> Result<T> getServiceError() {
        return getServiceError("服务器繁忙，请稍候重试！", null);
    }

    /**
     * 得到服务异常Result.
     *
     * @param message 用于设置Result.msg字段
     */
    public static <T> Result<T> getServiceError(String message) {
        return getServiceError(message, null);
    }

    /**
     * 得到服务异常Result.
     *
     * @param message 用于设置Result.msg字段
     * @param trace   用于设置Result.trace字段
     */
    public static <T> Result<T> getServiceError(String message, String trace) {
        Result<T> result = new Result<>(SERVICE_ERROR_STATUS, message, null, null, trace);
        return result;
    }


    /**
     * 得到正常结果.
     *
     * @param re 正常结果
     */
    public static <T> Result<T> getSuccessResult(T re) {
        Result<T> result = new Result<>(SUCCESS_STATUS, null, null, re);
        return result;
    }

    /**
     * 得到业务异常Result.
     *
     * @param msg  用于设置Result.msg字段
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getBusinessException(String msg, String code) {
        Result<T> result = new Result<>(BUSINESS_ERROR_STATUS, msg, code, null);
        return result;
    }

    /**
     * 得到业务异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getBusinessException(String code) {
        return getBusinessException(null, code);
    }

    /**
     * 得到请求参数非法异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getParamException(String code) {
        return getParamException(code, null);
    }

    /**
     * 得到请求参数非法异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getParamException(String code, String msg) {
        return new Result<>(PARAM_ERROR_STATUS, msg, code);
    }

    /**
     * 用于拷贝集合中的bean
     *
     * @param source      待拷贝集合
     * @param targetClass 目标对象类型
     * @return
     */
    public static List copyPropertiesForCollection(Collection source, Class targetClass) {
        List result = new ArrayList();
        if (source != null) {
            for (Object item : source) {
                try {
                    Object targetObject = targetClass.newInstance();
                    BeanUtils.copyProperties(item, targetObject);
                    result.add(targetObject);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return result;
    }

    public int getStatus() {
        return status;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public String getCode() {
        return code;
    }

    public String getTrace() {
        return trace;
    }


    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Result{");
        sb.append("status=").append(status);
        sb.append(", msg='").append(msg).append('\'');
        sb.append(", code='").append(code).append('\'');
        sb.append(", data=").append(data);
        sb.append('}');
        return sb.toString();
    }
}
